<!--
 * @Description: vscode自带注释
 * @Version: 2.0
 * @Autor: lhl
 * @Date: 2021-04-10 22:06:42
 * @LastEditors: lhl
 * @LastEditTime: 2021-05-09 20:25:13
-->
<template>
  <div class="vue3-grammer">
    <div class="num-box">{{ num }}----{{ newNum }}----{{ refData }}</div>
    <div class="change-num-btn">
      <van-button size="large" type="primary" @click="handleChange">改变数据</van-button>
    </div>
    <div class="from-box">
      <van-form @submit="onSubmit">
        <van-field
          v-model="username"
          name="username"
          label="用户名"
          placeholder="用户名"
          :rules="[{ required: true, message: '请填写用户名' }]"
        />
        <van-field
          v-model="password"
          type="password"
          name="password"
          label="密码"
          placeholder="密码"
          :rules="[{ required: true, message: '请填写密码' }]"
        />
        <child @reciveChildData="reciveFromChildData" />
        <div style="margin: 16px">
          <van-button round block type="primary" native-type="submit"> 提交表单 </van-button>
        </div>
      </van-form>
    </div>
    <!-- vant 组件使用 -->
    <div style="margin: 16px">
      <van-button round block type="success" @click="goNextPage">路由跳转</van-button>
    </div>
  </div>
</template>

<script lang="ts">
  // defineComponent最重要的是：在TypeScript下，给予了组件 正确的参数类型推断
  import { defineComponent, toRefs, reactive, getCurrentInstance, watch, computed, ref } from 'vue'
  //   beforeCreate created  -->用 setup 代替
  import {
    onBeforeMount,
    onMounted,
    onBeforeUpdate,
    onUpdated,
    onBeforeUnmount,
    onUnmounted
  } from 'vue'
  import { useRouter, useRoute } from 'vue-router'
  import child from './child.vue'

  export default defineComponent({
    name: 'vue3Grammer',
    components: { child },
    setup(props, context) {
      console.log(props, 'props', context, 'context')
      //这里的ctx  类似于vue2的this
      // 会报错 且开发环境可以生产环境会报错
      //   const { ctx: any } = getCurrentInstance()
      //   console.log(ctx, 'ctx')
      // 获取组件实例 用于高阶用法或库的开发
      // internalInstance.appContext.config.globalProperties // 访问 globalProperties
      const internalInstance = getCurrentInstance()
      console.log(internalInstance, 'internalInstance') // 访问 globalProperties

      const refData = ref(12) //ref包裹 变为响应式对象
      // 个人觉着还是这样写舒服一点 类似于vue2中的data
      const state = reactive({
        //函数接收一个普通对象，返回一个响应式的数据对象
        num: 0,
        username: '',
        password: ''
      })
      //计算属性 个人喜欢写在对象中 因为看得更清晰一下 防止计算属性方法等混在一起不好区分
      const computedData = {
        // 计算属性写法 别忘记引入 computed
        newNum: computed(() => state.num * 2)
      }
      const router = useRouter()
      console.log(router, 'this.$router')
      const route = useRoute()
      console.log(route, 'this.$route', route.meta)

      const methods = {
        // 改变数据
        handleChange: () => {
          state.num++
          // ref包裹的数据 必须用.value获取
          refData.value++
        },
        // 提交表单
        onSubmit: (values: object) => {
          console.log('submit', values)
        },
        // 跳转
        goNextPage() {
          //路由跳转
          router.push({
            name: 'home'
          })
        },
        // 父组件接收子组件的值
        reciveFromChildData(val: any) {
          console.log(val, 'val-来自子组件的值')
          state.username = val.username
          state.password = val.password
        }
        //网络请求
        // main.js传入的封装axios
        // async getUser() {
        //   try {
        //     let { data } = await userApi()
        //     console.log(data)
        //   } catch (error) {
        //     console.log(error)
        //   }
        // }
      }
      onBeforeMount(() => {
        console.log('生命周期---等同于vue2的 beforeMount')
      })

      onMounted(() => {
        // methods.getUser()
        console.log('生命周期---等同于vue2的 mounted')
      })

      onBeforeUpdate(() => {
        console.log('生命周期---等同于vue2的 beforeUpdate')
      })

      onUpdated(() => {
        console.log('生命周期---等同于vue2的 updated')
      })

      onBeforeUnmount(() => {
        console.log('生命周期---等同于vue2的 beforeUnmount')
      })

      onUnmounted(() => {
        console.log('生命周期---等同于vue2的 unmounted ')
      })

      // watch的使用
      watch(
        () => state.num,
        (value) => {
          console.log('num改变', value)
        }
      )
      return {
        ...toRefs(state), // 将响应式的对象变为普通对象 使用时不需要state.num 直接num即可使用
        ...methods, // 解构赋值
        ...computedData,
        refData
      }
    }
  })
</script>

<style lang="less" scoped>
  .num-box {
    background: #000;
    color: #fff;
    font-size: 16px;
    text-align: center;
    padding: 10px 0;
  }
  .change-num-btn {
    margin: 8px 0;
  }
</style>
